home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / tex / archives / pbmtopk.lzh / pbmtopk / src / pbmtopk.c < prev    next >
C/C++ Source or Header  |  1992-05-16  |  27KB  |  1,059 lines

  1. /*
  2.   pbmtopk, adapted from "pxtopk.c by tomas rokicki" by AJCD 1/8/90
  3.  
  4.   compile with: cc -o pbmtopk pbmtopk.c -lm -lpbm
  5.   */
  6.  
  7. #include <stdio.h>
  8. #include <pbm.h>
  9. #include <ctype.h>
  10.  
  11. #ifdef A_FORCEPROTO
  12. #undef A_FORCEPROTO
  13. /* This source is a complete mess.  It looks like a direct Pascal->C
  14.    conversion. I don't even want to try to fully prototype it.
  15.    I would end up changing half the stuff. */
  16. #else /* A_FORCEPROTO */
  17. extern double atof();
  18. #endif /* A_FORCEPROTO */
  19.  
  20. #define MAXPKCHAR 256
  21. #define MAXOPTLINE 200
  22. #define MAXWIDTHTAB 256
  23. #define MAXHEIGHTTAB 16
  24. #define MAXDEPTHTAB 16
  25. #define MAXITALICTAB 64
  26. #define MAXPARAMS 30
  27. #define NAMELENGTH 80
  28.  
  29. #define true (1)
  30. #define false (0)
  31. #define chr(a) a
  32.  
  33. #define round(a) ((int)(a+.5))
  34. #define fixword(d) ((int)((double)(d)*1048576))
  35. #define unfixword(f) ((double)(f) / 1048576)
  36. #define fixrange(f) ((f) < 16777216 && (f) > -16777216)
  37. #define designunits(p) ((p)*72.27/(double)resolution/unfixword(designsize))
  38.  
  39. /* character flags: in order of appearance in option files. */
  40. #define XOFFSET     1
  41. #define YOFFSET     2
  42. #define HORZESC     4
  43. #define VERTESC     8
  44. #define TFMWIDTH   16
  45. #define TFMHEIGHT  32
  46. #define TFMDEPTH   64
  47. #define TFMITALIC 128
  48.  
  49. typedef int integer ;
  50. typedef char quarterword ;
  51. typedef char boolean ;
  52. typedef quarterword ASCIIcode ;
  53. typedef quarterword eightbits ;
  54. typedef FILE *bytefile ;
  55. typedef unsigned char byte ;
  56.  
  57. integer resolution, designsize ;
  58. char *filename[MAXPKCHAR] ;
  59.  
  60. integer xoffset[MAXPKCHAR] ;
  61. integer yoffset[MAXPKCHAR] ;
  62. integer horzesc[MAXPKCHAR] ;
  63. integer vertesc[MAXPKCHAR] ;
  64.  
  65. byte tfmindex[MAXPKCHAR] ;
  66. byte hgtindex[MAXPKCHAR] ;
  67. byte depindex[MAXPKCHAR] ;
  68. byte italindex[MAXPKCHAR] ;
  69. byte charflags[MAXPKCHAR] ;
  70.  
  71. bit **bitmap ;
  72. integer smallestch, largestch ;
  73. integer emwidth ;
  74. integer checksum ;
  75. char *codingscheme = "GRAPHIC" ;
  76. char *familyname = "PBM" ;
  77.  
  78. integer widthtab[MAXWIDTHTAB] ; /* TFM widths */
  79. integer numwidth ;      /* number of entries in width table */
  80. integer heighttab[MAXHEIGHTTAB] ;
  81. integer numheight ;
  82. integer depthtab[MAXDEPTHTAB] ;
  83. integer numdepth ;
  84. integer italictab[MAXITALICTAB] ;
  85. integer numitalic ;
  86. integer parameters[MAXPARAMS] ;
  87. integer numparam ;
  88.  
  89. ASCIIcode xord[128] ;
  90. char xchr[256] ;
  91. bytefile tfmfile, pkfile ;
  92. char tfmname[NAMELENGTH+1], pkname[NAMELENGTH+1] ;
  93. integer pkloc ;
  94. integer bitweight ;
  95. integer outputbyte ;
  96. integer car ;
  97. integer hppp ;
  98. integer width ;
  99. integer height ;
  100. integer power[32] ;
  101.  
  102. integer
  103. compute_checksum()
  104. {
  105.   /*
  106.     begin
  107.       c0:=bc; c1:=ec; c2:=bc; c3:=ec;
  108.       for c:=bc to ec do if char_wd[c]>0 then
  109.         begin
  110.           temp_width:=memory[char_wd[c]];
  111.           if design_units<>unity then
  112.             temp_width:=round((temp_width/design_units)*1048576.0);
  113.           temp_width:=temp_width + (c+4)*@'20000000; {this should be positive}
  114.           c0:=(c0+c0+temp_width) mod 255;
  115.           c1:=(c1+c1+temp_width) mod 253;
  116.           c2:=(c2+c2+temp_width) mod 251;
  117.           c3:=(c3+c3+temp_width) mod 247;
  118.         end;
  119.       header_bytes[check_sum_loc]:=c0;
  120.       header_bytes[check_sum_loc+1]:=c1;
  121.       header_bytes[check_sum_loc+2]:=c2;
  122.       header_bytes[check_sum_loc+3]:=c3;
  123.     end
  124.     */
  125. }
  126.  
  127. #define add_tfmwidth(v) (add_tfmtable(widthtab, &numwidth, v, MAXWIDTHTAB,\
  128.                                       "TFM width"))
  129. #define add_tfmheight(v) (add_tfmtable(heighttab, &numheight, v, MAXHEIGHTTAB,\
  130.                                        "TFM height"))
  131. #define add_tfmdepth(v) (add_tfmtable(depthtab, &numdepth, v, MAXDEPTHTAB,\
  132.                                       "TFM depth"))
  133. #define add_tfmitalic(v) (add_tfmtable(italictab, &numitalic, v, MAXITALICTAB,\
  134.                                        "Italic correction"))
  135. byte
  136. add_tfmtable(table, count, value, max1, name)
  137.      integer *table, *count, value, max1;
  138.      char *name;
  139. {
  140.   integer i;
  141.   for (i = 0; i < *count; i++) /* search for value in tfm table */
  142.     if (table[i] == value) return (byte)i;
  143.   if (*count >= max1) {
  144.     fprintf(stderr, "Too many values in %s table!\n", name) ;
  145.     jumpout();
  146.   }
  147.   if (!fixrange(value)) {
  148.     fprintf(stderr, " %s %f for char %d out of range!\n",
  149.             name, unfixword(value), car);
  150.     jumpout();
  151.   }
  152.   table[*count] = value ;
  153.   return (*count)++ ;
  154. }
  155.  
  156. add_suffix(name, suffix)
  157.      char *name, *suffix ;
  158. {
  159.   int haveext = 0;
  160.   if (name && strcmp(name, "-")) {
  161.     while (*name) {
  162.       if (*name == '/') haveext = 0 ;
  163.       else if (*name == '.') haveext = 1 ;
  164.       name++ ;
  165.     }
  166.     if (!haveext) {
  167.       *name++ = '.';
  168.       strcpy(name,suffix) ;
  169.     }
  170.   }
  171. }
  172.  
  173. initialize()
  174. {
  175.   integer i ;
  176.   fprintf(stderr, "This is PBMtoPK, C Version 2.3\n") ;
  177.   for (i = 0 ; i <= 31 ; i ++) xchr[i] = '?' ;
  178.   xchr[32] = ' ' ;
  179.   xchr[33] = '!' ;
  180.   xchr[34] = '"' ;
  181.   xchr[35] = '#' ;
  182.   xchr[36] = '$' ;
  183.   xchr[37] = '%' ;
  184.   xchr[38] = '&' ;
  185.   xchr[39] = '\'' ;
  186.   xchr[40] = '(' ;
  187.   xchr[41] = ')' ;
  188.   xchr[42] = '*' ;
  189.   xchr[43] = '+' ;
  190.   xchr[44] = ',' ;
  191.   xchr[45] = '-' ;
  192.   xchr[46] = '.' ;
  193.   xchr[47] = '/' ;
  194.   xchr[48] = '0' ;
  195.   xchr[49] = '1' ;
  196.   xchr[50] = '2' ;
  197.   xchr[51] = '3' ;
  198.   xchr[52] = '4' ;
  199.   xchr[53] = '5' ;
  200.   xchr[54] = '6' ;
  201.   xchr[55] = '7' ;
  202.   xchr[56] = '8' ;
  203.   xchr[57] = '9' ;
  204.   xchr[58] = ':' ;
  205.   xchr[59] = ';' ;
  206.   xchr[60] = '<' ;
  207.   xchr[61] = '=' ;
  208.   xchr[62] = '>' ;
  209.   xchr[63] = '?' ;
  210.   xchr[64] = '@' ;
  211.   xchr[65] = 'A' ;
  212.   xchr[66] = 'B' ;
  213.   xchr[67] = 'C' ;
  214.   xchr[68] = 'D' ;
  215.   xchr[69] = 'E' ;
  216.   xchr[70] = 'F' ;
  217.   xchr[71] = 'G' ;
  218.   xchr[72] = 'H' ;
  219.   xchr[73] = 'I' ;
  220.   xchr[74] = 'J' ;
  221.   xchr[75] = 'K' ;
  222.   xchr[76] = 'L' ;
  223.   xchr[77] = 'M' ;
  224.   xchr[78] = 'N' ;
  225.   xchr[79] = 'O' ;
  226.   xchr[80] = 'P' ;
  227.   xchr[81] = 'Q' ;
  228.   xchr[82] = 'R' ;
  229.   xchr[83] = 'S' ;
  230.   xchr[84] = 'T' ;
  231.   xchr[85] = 'U' ;
  232.   xchr[86] = 'V' ;
  233.   xchr[87] = 'W' ;
  234.   xchr[88] = 'X' ;
  235.   xchr[89] = 'Y' ;
  236.   xchr[90] = 'Z' ;
  237.   xchr[91] = '[' ;
  238.   xchr[92] = '\\' ;
  239.   xchr[93] = ']' ;
  240.   xchr[94] = '^' ;
  241.   xchr[95] = '_' ;
  242.   xchr[96] = '`' ;
  243.   xchr[97] = 'a' ;
  244.   xchr[98] = 'b' ;
  245.   xchr[99] = 'c' ;
  246.   xchr[100] = 'd' ;
  247.   xchr[101] = 'e' ;
  248.   xchr[102] = 'f' ;
  249.   xchr[103] = 'g' ;
  250.   xchr[104] = 'h' ;
  251.   xchr[105] = 'i' ;
  252.   xchr[106] = 'j' ;
  253.   xchr[107] = 'k' ;
  254.   xchr[108] = 'l' ;
  255.   xchr[109] = 'm' ;
  256.   xchr[110] = 'n' ;
  257.   xchr[111] = 'o' ;
  258.   xchr[112] = 'p' ;
  259.   xchr[113] = 'q' ;
  260.   xchr[114] = 'r' ;
  261.   xchr[115] = 's' ;
  262.   xchr[116] = 't' ;
  263.   xchr[117] = 'u' ;
  264.   xchr[118] = 'v' ;
  265.   xchr[119] = 'w' ;
  266.   xchr[120] = 'x' ;
  267.   xchr[121] = 'y' ;
  268.   xchr[122] = 'z' ;
  269.   xchr[123] = '{' ;
  270.   xchr[124] = '|' ;
  271.   xchr[125] = '}' ;
  272.   xchr[126] = '~' ;
  273.   for (i = 127 ; i <= 255 ; i ++) xchr[i] = '?' ;
  274.   for (i = 0 ; i <= 127 ; i ++) xord[chr(i)] = 32 ;
  275.   for (i = 32 ; i <= 126 ; i ++) xord[xchr[i]] = i ;
  276.   for (i = 0 ; i < 32 ; i++) power[i] = 1 << i ;
  277.   for (i = 0; i < MAXPKCHAR; i++) {
  278.     filename[i] = NULL;
  279.     charflags[i] = 0;
  280.   }
  281.   pkloc = 0 ;
  282.   designsize = fixword(1.0) ;
  283.   numparam = 0;
  284.   widthtab[0] = heighttab[0] = depthtab[0] = italictab[0] = 0 ;
  285.   numwidth = numheight = numdepth = numitalic = 1;
  286.   smallestch = MAXPKCHAR ;
  287.   largestch = -1 ;
  288.   emwidth = 0 ;
  289. }
  290.  
  291. jumpout()
  292. {
  293.   exit(1) ;
  294. }
  295.  
  296. pkbyte(b)
  297.      integer b ;
  298. {
  299.   if (b < 0) b = b + 256 ;
  300.   putc(b, pkfile) ;
  301.   pkloc++ ;
  302. }
  303.  
  304. pkhalfword(a)
  305.      integer a ;
  306. {
  307.   if (a < 0) a = a + 65536 ;
  308.   pkbyte(a >> 8) ;
  309.   pkbyte(a & 255) ;
  310. }
  311.  
  312. pkthreebytes(a)
  313.      integer a ;
  314. {
  315.   pkbyte((a>>16) & 255) ;
  316.   pkbyte((a>>8) & 255) ;
  317.   pkbyte(a & 255) ;
  318. }
  319.  
  320. pkword(a)
  321.      integer a ;
  322. {
  323.   pkbyte((a>>24) & 255) ;
  324.   pkbyte((a>>16) & 255) ;
  325.   pkbyte((a>>8) & 255) ;
  326.   pkbyte(a & 255) ;
  327. }
  328.  
  329. pknyb(a)
  330.      integer a ;
  331. {
  332.   if (bitweight == 16) {
  333.     outputbyte = (a<<4) ;
  334.     bitweight = 1 ;
  335.   } else {
  336.     pkbyte(outputbyte + a) ;
  337.     bitweight = 16 ;
  338.   }
  339. }
  340.  
  341. writepreamble()
  342. {
  343.   integer i ;
  344.   char *comment = "PBMtoPK 2.3 output" ;
  345.  
  346.   pkbyte(247) ;
  347.   pkbyte(89) ;
  348.   pkbyte(strlen(comment)) ;
  349.   for (i = 0 ; i < strlen(comment); i++) pkbyte(xord[comment[i]]) ;
  350.   pkword(designsize) ;
  351.   pkword(checksum) ; /* checksum; calculate if possible */
  352.   pkword(hppp) ;
  353.   pkword(hppp) ;
  354. }
  355.  
  356. writepostamble()
  357. {
  358.   pkbyte(245) ;
  359.   while ((pkloc % 4 != 0)) pkbyte(246) ;
  360.   fprintf(stderr, "%d bytes written to packed file.\n", pkloc) ;
  361. }
  362.  
  363. tfmbyte(b)
  364.      integer b ;
  365. {
  366.   if (b < 0) b = b + 256 ;
  367.   putc(b, tfmfile) ;
  368. }
  369.  
  370. tfmhalfword(a)
  371.      integer a ;
  372. {
  373.   if (a < 0) a = a + 65536 ;
  374.   tfmbyte(a >> 8) ;
  375.   tfmbyte(a & 255) ;
  376. }
  377.  
  378. tfmword(a)
  379.      integer a ;
  380. {
  381.   tfmbyte((a>>24) & 255) ;
  382.   tfmbyte((a>>16) & 255) ;
  383.   tfmbyte((a>>8) & 255) ;
  384.   tfmbyte(a & 255) ;
  385. }
  386.  
  387. writetfmfile()
  388. {
  389.   integer totallength ;
  390.   integer headersize = 17;
  391.   integer i ;
  392.  
  393.   if (largestch - smallestch < 0) {
  394.      largestch = 0;
  395.      smallestch = 1;
  396.   }
  397.   if (numparam < 7) /* set default parameters */
  398.     switch (numparam) {
  399.     case 0: /* slant */
  400.       parameters[numparam++] = 0 ;
  401.     case 1: /* space */
  402.       parameters[numparam++] = fixword(designunits(emwidth/3.0));
  403.     case 2: /* space_stretch */
  404.       parameters[numparam++] = fixword(unfixword(parameters[1])/2.0) ;
  405.     case 3: /* space_shrink */
  406.       parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ;
  407.     case 4: /* x_height */
  408.       parameters[numparam++] = fixword(0.45);
  409.     case 5: /* quad */
  410.       parameters[numparam++] = fixword(designunits(emwidth)) ;
  411.     case 6: /* extra_space */
  412.       parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ;
  413.     }
  414.   totallength = 6 + headersize + (largestch+1-smallestch) +
  415.     numwidth + numheight + numdepth + numitalic + numparam ;
  416.   /* lengths */
  417.   tfmhalfword(totallength) ;
  418.   tfmhalfword(headersize) ;
  419.   tfmhalfword(smallestch) ;
  420.   tfmhalfword(largestch) ;
  421.   tfmhalfword(numwidth) ;
  422.   tfmhalfword(numheight) ;
  423.   tfmhalfword(numdepth) ;
  424.   tfmhalfword(numitalic) ;
  425.   tfmhalfword(0) ; /* lig/kern table */
  426.   tfmhalfword(0) ; /* kern table */
  427.   tfmhalfword(0) ; /* extensible char table */
  428.   tfmhalfword(numparam) ;
  429.   /* header */
  430.   tfmword(checksum) ;
  431.   tfmword(designsize) ;
  432.   if (strlen(codingscheme) > 39) tfmbyte(39) ;
  433.   else tfmbyte(strlen(codingscheme)) ;
  434.   for (i = 0; i < 39; i++)
  435.     if (*codingscheme) tfmbyte(xord[*codingscheme++]) ;
  436.     else tfmbyte(0) ;
  437.   if (strlen(familyname) > 19) tfmbyte(19) ;
  438.   else tfmbyte(strlen(familyname)) ;
  439.   for (i = 0; i < 19; i++)
  440.     if (*familyname) tfmbyte(xord[*familyname++]) ;
  441.     else tfmbyte(0) ;
  442.   /* char_info */
  443.   for (car = smallestch; car <= largestch; car++)
  444.     if (filename[car]) {
  445.       tfmbyte(tfmindex[car]) ;
  446.       tfmbyte((hgtindex[car]<<4) + depindex[car]) ;
  447.       tfmbyte(italindex[car]<<2) ;
  448.       tfmbyte(0) ;
  449.     } else tfmword(0) ;
  450.   /* width */
  451.   for (i = 0; i < numwidth; i++) tfmword(widthtab[i]) ;
  452.   /* height */
  453.   for (i = 0; i < numheight; i++) tfmword(heighttab[i]) ;
  454.   /* depth */
  455.   for (i = 0; i < numdepth; i++) tfmword(depthtab[i]) ;
  456.   /* italic */
  457.   for (i = 0; i < numitalic; i++) tfmword(italictab[i]) ;
  458.   /* no lig_kern, kern, or exten */
  459.   /* param */
  460.   for (i = 0; i < numparam; i++)
  461.     if (i && (!fixrange(parameters[i]))) {
  462.       fprintf(stderr, " Parameter %d out of range (-p)!\n", i);
  463.       jumpout();
  464.     }
  465.     else tfmword(parameters[i]) ;
  466.   fprintf(stderr, "%d bytes written to tfm file.\n", totallength*4) ;
  467. }
  468.  
  469. readcharacter()
  470. {
  471.   FILE *fp;
  472.  
  473.   if (!strcmp(filename[car], "-")) fp = stdin;
  474.   else if ((fp = fopen(filename[car], "r")) == NULL) {
  475.     fprintf(stderr, " Can't open pbm file %s!\n", filename[car]);
  476.     jumpout();
  477.   }
  478.   bitmap = pbm_readpbm(fp, &width, &height) ;
  479.   if (fp != stdin) fclose(fp) ;
  480.  
  481.   if ((charflags[car] & HORZESC) == 0) horzesc[car] = width ;
  482.   if ((charflags[car] & VERTESC) == 0) vertesc[car] = 0;
  483.   if ((charflags[car] & XOFFSET) == 0) xoffset[car] = 0;
  484.   if ((charflags[car] & YOFFSET) == 0) yoffset[car] = height-1;
  485.   if ((charflags[car] & TFMWIDTH) == 0)
  486.     tfmindex[car] = add_tfmwidth(fixword(designunits(width)));
  487.   if ((charflags[car] & TFMHEIGHT) == 0)
  488.     hgtindex[car] = add_tfmheight(fixword(designunits(yoffset[car]+1)));
  489.   if ((charflags[car] & TFMDEPTH) == 0)
  490.     depindex[car] = add_tfmdepth(fixword(designunits(height-1-yoffset[car])));
  491.   if ((charflags[car] & TFMITALIC) == 0) italindex[car] = 0;
  492.  
  493.   if (car < smallestch) smallestch = car;
  494.   if (car > largestch) largestch = car;
  495.   if (width > emwidth) emwidth = width ;
  496. }
  497.  
  498. int
  499. equal(row1, row2)
  500.      bit *row1, *row2 ;
  501. {
  502.   integer i ;
  503.  
  504.   for (i = 0; i < width; i++)
  505.     if (row1[i] != row2[i]) return (0) ;
  506.   return(1) ;
  507. }
  508.  
  509. shipcharacter()
  510. {
  511.   integer compsize ;
  512.   integer i, j, k ;
  513.   bit *zerorow, *onesrow ;
  514.   integer *repeatptr, *bitcounts ;
  515.   integer count ;
  516.   integer test ;
  517.   integer curptr, rowptr ;
  518.   integer bitval ;
  519.   integer repeatflag ;
  520.   integer colptr ;
  521.   integer currepeat ;
  522.   integer dynf ;
  523.   integer deriv[14] ;
  524.   integer bcompsize ;
  525.   boolean firston ;
  526.   integer flagbyte ;
  527.   boolean state ;
  528.   boolean on ;
  529.   integer hbit ;
  530.   integer pbit ;
  531.   boolean ron, son ;
  532.   integer rcount, scount ;
  533.   integer ri, si ;
  534.   integer max2 ;
  535.   integer predpkloc ;
  536.   integer buff ;
  537.  
  538.   integer tfwid = widthtab[tfmindex[car]] ;
  539.   integer hesc = horzesc[car] ;
  540.   integer vesc = vertesc[car] ;
  541.   integer xoff = xoffset[car] ;
  542.   integer yoff = yoffset[car] ;
  543.  
  544.   zerorow = pbm_allocrow(width) ;
  545.   onesrow = pbm_allocrow(width) ;
  546.   repeatptr =
  547.     (integer *)malloc((unsigned int)((height+1)*sizeof(integer))) ;
  548.   bitcounts =
  549.     (integer *)malloc((unsigned int)((height*width)*sizeof(integer))) ;
  550.   if (repeatptr == NULL || bitcounts == NULL) {
  551.      fprintf(stderr, " Out of memory while allocating bit counts!\n");
  552.      jumpout() ;
  553.   }
  554.   for (i = 0 ; i < width ; i++) {
  555.     zerorow[i] = PBM_WHITE ;
  556.     onesrow[i] = PBM_BLACK ;
  557.   }
  558.   for (i=0; i < height; i++) {
  559.     if (equal(bitmap[i], zerorow))
  560.       repeatptr[i] = 0 ;
  561.     else if (equal(bitmap[i], onesrow))
  562.       repeatptr[i] = 0 ;
  563.     else if (i + 1 < height && equal(bitmap[i],bitmap[i+1]))
  564.       repeatptr[i] = 1 ;
  565.     else
  566.       repeatptr[i] = 0 ;
  567.   }
  568.   i = 0 ;
  569.   while (i < height) {
  570.     k = i ;
  571.     while (repeatptr[k] == 1) k++ ;
  572.     repeatptr[i] = k - i ;
  573.     i = k + 1 ;
  574.   }
  575.   repeatptr[i] = 0 ;
  576.   colptr = width - 1 ;
  577.   repeatflag = currepeat = curptr = count = rowptr = 0 ;
  578.   test = PBM_WHITE ;
  579.   do {
  580.     colptr++ ;
  581.     if (colptr == width) {
  582.       colptr = 0 ;
  583.       rowptr = currepeat ;
  584.       if (repeatptr[currepeat] > 0) {
  585.         repeatflag = repeatptr[currepeat] ;
  586.         currepeat += repeatflag ;
  587.         rowptr += repeatflag ;
  588.       }
  589.       currepeat++ ;
  590.     }
  591.     if (rowptr >= height) bitval = -1 ;
  592.     else bitval = bitmap[rowptr][colptr] ;
  593.     if (bitval == test) count++ ;
  594.     else {
  595.       bitcounts[curptr++] = count ;
  596.       if (curptr+3 >= height*width) {
  597.         fprintf(stderr, " Out of memory while saving character counts!\n");
  598.         jumpout() ;
  599.       }
  600.       count = 1 ;
  601.       test = bitval ;
  602.       if (repeatflag > 0) {
  603.         bitcounts[curptr++] = -repeatflag ;
  604.         repeatflag = 0 ;
  605.       }
  606.     }
  607.   } while (test != -1) ;
  608.   bitcounts[curptr] = 0 ;
  609.   bitcounts[curptr + 1] = 0 ;
  610.   for (i = 1 ; i <= 13 ; i ++) deriv[i] = 0 ;
  611.   i = firston = (bitcounts[0] == 0) ;
  612.   compsize = 0 ;
  613.   while (bitcounts[i] != 0) {
  614.     j = bitcounts[i] ;
  615.     if (j == -1) compsize++ ;
  616.     else {
  617.       if (j < 0) {
  618.         compsize++ ;
  619.         j = -j ;
  620.       }
  621.       if (j < 209) compsize += 2 ;
  622.       else {
  623.         k = j - 193 ;
  624.         while (k >= 16) {
  625.           k >>= 4 ;
  626.           compsize += 2 ;
  627.         }
  628.         compsize++ ;
  629.       }
  630.       if (j < 14) (deriv[j])-- ;
  631.       else if (j < 209) (deriv[(223 - j) / 15])++ ;
  632.       else {
  633.         k = 16 ;
  634.         while (((k<<4) < j + 3)) k <<= 4 ;
  635.         if (j - k <= 192)
  636.           deriv[(207 - j + k) / 15] += 2 ;
  637.       }
  638.     }
  639.     i++ ;
  640.   }
  641.   bcompsize = compsize ;
  642.   dynf = 0 ;
  643.   for (i = 1 ; i <= 13 ; i ++) {
  644.     compsize += deriv[i] ;
  645.     if (compsize <= bcompsize) {
  646.       bcompsize = compsize ;
  647.       dynf = i ;
  648.     }
  649.   }
  650.   compsize = ((bcompsize + 1)>>1) ;
  651.   if ((compsize > ((height*width+7)>>3)) || (height*width == 0)) {
  652.     compsize = ((height*width+7)>>3) ;
  653.     dynf = 14 ;
  654.   }
  655.   flagbyte = (dynf<<4) ;
  656.   if (firston) flagbyte |= 8 ;
  657.   if ((tfwid > 16777215) || (tfwid < 0) || (hesc < 0) || (vesc != 0) ||
  658.       (compsize > 196579) || (width > 65535) || (height > 65535) ||
  659.       (xoff > 32767) || (yoff > 32767) || (xoff < -32768) || (yoff < -32768)) {
  660.     flagbyte |= 7 ;
  661.     pkbyte(flagbyte) ;
  662.     compsize += 28 ;
  663.     pkword(compsize) ;
  664.     pkword(car) ;
  665.     predpkloc = pkloc + compsize ;
  666.     pkword(tfwid) ;
  667.     pkword(hesc<<16) ;
  668.     pkword(vesc<<16) ;
  669.     pkword(width) ;
  670.     pkword(height) ;
  671.     pkword(xoff) ;
  672.     pkword(yoff) ;
  673.   } else if ((hesc > 255) || (width > 255) || (height > 255) ||
  674.            (xoff > 127) || (yoff > 127) || (xoff < -128) ||
  675.            (yoff < -128) || (compsize > 1016)) {
  676.     compsize += 13 ;
  677.     flagbyte += (compsize>>16) + 4 ;
  678.     pkbyte(flagbyte) ;
  679.     pkhalfword(compsize & 65535) ;
  680.     pkbyte(car) ;
  681.     predpkloc = pkloc + compsize ;
  682.     pkthreebytes(tfwid) ;
  683.     pkhalfword(hesc) ;
  684.     pkhalfword(width) ;
  685.     pkhalfword(height) ;
  686.     pkhalfword(xoff) ;
  687.     pkhalfword(yoff) ;
  688.   } else {
  689.     compsize += 8 ;
  690.     flagbyte = flagbyte + (compsize>>8) ;
  691.     pkbyte(flagbyte) ;
  692.     pkbyte(compsize & 255) ;
  693.     pkbyte(car) ;
  694.     predpkloc = pkloc + compsize ;
  695.     pkthreebytes(tfwid) ;
  696.     pkbyte(hesc) ;
  697.     pkbyte(width) ;
  698.     pkbyte(height) ;
  699.     pkbyte(xoff) ;
  700.     pkbyte(yoff) ;
  701.   }
  702.   if (dynf != 14) {
  703.     bitweight = 16 ;
  704.     max2 = 208 - 15 * dynf ;
  705.     i = firston ;
  706.     while (bitcounts[i] != 0) {
  707.       j = bitcounts[i] ;
  708.       if (j == - 1) pknyb(15) ;
  709.       else {
  710.         if (j < 0) {
  711.           pknyb(14) ;
  712.           j = -j ;
  713.         }
  714.         if (j <= dynf) pknyb(j) ;
  715.         else if (j <= max2) {
  716.           j -= dynf + 1 ;
  717.           pknyb((j >> 4) + dynf + 1) ;
  718.           pknyb((j & 15)) ;
  719.         } else {
  720.           j -= max2 - 15 ;
  721.           k = 16 ;
  722.           while (k <= j) {
  723.             k <<= 4 ;
  724.             pknyb(0) ;
  725.           }
  726.           while (k > 1) {
  727.             k >>= 4 ;
  728.             pknyb(j / k) ;
  729.             j = j % k ;
  730.           }
  731.         }
  732.       }
  733.       i++ ;
  734.     }
  735.     if (bitweight != 16) pkbyte(outputbyte) ;
  736.   } else {
  737.     buff = 0 ;
  738.     pbit = 8 ;
  739.     i = firston ;
  740.     hbit = width ;
  741.     on = ! firston ;
  742.     state = false ;
  743.     count = repeatflag = 0 ;
  744.     while ((bitcounts[i] != 0) || state || (count > 0)) {
  745.       if (state) {
  746.         count = rcount ;
  747.         i = ri ;
  748.         on = ron ;
  749.         repeatflag-- ;
  750.       } else {
  751.         rcount = count ;
  752.         ri = i ;
  753.         ron = on ;
  754.       }
  755.       do {
  756.         if (count == 0) {
  757.           if (bitcounts[i] < 0) {
  758.             if (! state) repeatflag = -bitcounts[i] ;
  759.             i++ ;
  760.           }
  761.           count = bitcounts[i] ;
  762.           i++ ;
  763.           on = !on ;
  764.         }
  765.         if ((count >= pbit) && (pbit < hbit)) {
  766.           if (on) buff += power[pbit] - 1 ;
  767.           pkbyte(buff) ;
  768.           buff = 0 ;
  769.           hbit -= pbit ;
  770.           count -= pbit ;
  771.           pbit = 8 ;
  772.         } else if ((count < pbit) && (count < hbit)) {
  773.           if (on) buff += power[pbit] - power[pbit - count] ;
  774.           pbit -=  count ;
  775.           hbit -= count ;
  776.           count = 0 ;
  777.         } else {
  778.           if (on) buff += power[pbit] - power[pbit - hbit] ;
  779.           count -= hbit ;
  780.           pbit -= hbit ;
  781.           hbit = width ;
  782.           if (pbit == 0) {
  783.             pkbyte(buff) ;
  784.             buff = 0 ;
  785.             pbit = 8 ;
  786.           }
  787.         }
  788.       } while (hbit != width) ;
  789.       if (state && (repeatflag == 0)) {
  790.         count = scount ;
  791.         i = si ;
  792.         on = son ;
  793.         state = false ;
  794.       } else if (! state && (repeatflag > 0)) {
  795.         scount = count ;
  796.         si = i ;
  797.         son = on ;
  798.         state = true ;
  799.       }
  800.     }
  801.     if (pbit != 8) pkbyte(buff) ;
  802.   }
  803.   if (predpkloc != pkloc) {
  804.     fprintf(stderr, " Bad predicted character length: character %d!\n", car);
  805.     jumpout() ;
  806.   }
  807.   pbm_freerow(zerorow);
  808.   pbm_freerow(onesrow);
  809.   free((char *)repeatptr);
  810.   free((char *)bitcounts);
  811. }
  812.  
  813. usage()
  814. {
  815.   fprintf(stderr, " Usage: pbmtopk pkfile[.pk] tfmfile[.tfm] dpi\n") ;
  816.   fprintf(stderr, "                [-s designsize] [-p num param...]\n");
  817.   fprintf(stderr, "                [-C codingscheme ] [-F family]\n");
  818.   fprintf(stderr, "                [-c num | <char>]...\n");
  819.   fprintf(stderr, " <char> is:     [-W tfmwidth] [-H tfmheight] [-D tfmdepth]\n");
  820.   fprintf(stderr, "                [-I ital_corr] [-h horiz] [-v vert]\n") ;
  821.   fprintf(stderr, "                [-x xoffset] [-y yoffset] file\n") ;
  822.   fprintf(stderr, " or:            -f optfile\n") ;
  823.   jumpout() ;
  824. }
  825.  
  826. checkchar()
  827. {
  828.   if (car < 0 || car >= MAXPKCHAR) {
  829.     fprintf(stderr, " Character must be in range 0 to %d (-c)!\n",
  830.             MAXPKCHAR-1) ;
  831.     jumpout() ;
  832.   }
  833. }
  834.  
  835. optionfile(name)
  836.      char *name ;
  837. {
  838.   FILE *fp ;
  839.   char buffer[MAXOPTLINE] ;
  840.  
  841.   if (!strcmp(name, "-")) fp = stdin ;
  842.   else if ((fp = fopen(name, "r")) == NULL) {
  843.     fprintf(stderr, " Can't open option file %s!\n", name) ;
  844.     jumpout() ;
  845.   }
  846.   while (!feof(fp)) {
  847.     char *here = buffer;
  848.  
  849.     if (fgets(buffer, MAXOPTLINE, fp) == NULL) break ;
  850.     while (isspace(*here)) here++ ;
  851.     if (*here && *here == '=') {
  852.       if (sscanf(here+1, "%d", &car) != 1) {
  853.         fprintf(stderr, "Bad option file line %s!\n", buffer) ;
  854.         jumpout() ;
  855.       }
  856.     } else if (*here && *here != '%' && *here != '#') {
  857.       char str[NAMELENGTH] ;
  858.       integer i, n;
  859.  
  860.       checkchar() ;
  861.       if (sscanf(here, "%s%n", str, &n) != 1) {
  862.         fprintf(stderr, "Bad option file line %s!\n", buffer) ;
  863.         jumpout() ;
  864.       }
  865.       filename[car] =
  866.         (char *)malloc((unsigned int)(sizeof(char)*(strlen(str)+1))) ;
  867.       strcpy(filename[car], str) ;
  868.       for (i = 1; i < 256; i<<=1) {
  869.         here += n;
  870.         if (sscanf(here, "%s%n", str, &n) != 1) break ;
  871.         if (strcmp(str, "*")) {
  872.           charflags[car] |= i ;
  873.           switch (i) {
  874.           case XOFFSET:
  875.             xoffset[car] = atoi(str) ;
  876.             break ;
  877.           case YOFFSET:
  878.             yoffset[car] = atoi(str) ;
  879.             break ;
  880.           case HORZESC:
  881.             horzesc[car] = atoi(str) ;
  882.             break ;
  883.           case VERTESC:
  884.             vertesc[car] = atoi(str) ;
  885.             break ;
  886.           case TFMWIDTH:
  887.             tfmindex[car] = add_tfmwidth(fixword(atof(str))) ;
  888.             break ;
  889.           case TFMHEIGHT:
  890.             hgtindex[car] = add_tfmheight(fixword(atof(str))) ;
  891.             break ;
  892.           case TFMDEPTH:
  893.             depindex[car] = add_tfmdepth(fixword(atof(str))) ;
  894.             break ;
  895.           case TFMITALIC:
  896.             italindex[car] = add_tfmitalic(fixword(atof(str))) ;
  897.             break ;
  898.           }
  899.         }
  900.       }
  901.       car++ ;
  902.     }
  903.   }
  904.   if (fp != stdin) fclose(fp) ;
  905. }
  906.  
  907. dialog(gargc, gargv)
  908.      int gargc ;
  909.      char **gargv ;
  910. {
  911.   integer i, hesc, vesc, xoff, yoff, tfwid, tfdep, tfhgt, tfital ;
  912.   byte flags ;
  913.  
  914.   if (--gargc < 1) usage() ;
  915.   strcpy(pkname, *++gargv) ;
  916.   add_suffix(pkname, "pk") ;
  917.  
  918.   if (--gargc < 1) usage() ;
  919.   strcpy(tfmname, *++gargv) ;
  920.   add_suffix(tfmname, "tfm") ;
  921.  
  922.   if (--gargc < 1) usage() ;
  923.   resolution = atoi(*++gargv) ;
  924.   if (resolution < 1 || resolution > 32767) {
  925.     fprintf(stderr, " Unlikely resolution %d dpi!\n", resolution);
  926.     jumpout();
  927.   }
  928.  
  929.   car = flags = hesc = vesc = xoff = yoff = tfwid = 0;
  930.   while (++gargv, --gargc) {
  931.     if (gargv[0][0] == '-' && gargv[0][1]) {
  932.       char c, *p;
  933.       c = gargv[0][1] ;
  934.       if (gargv[0][2]) p = *gargv + 2 ;
  935.       else if (++gargv, --gargc) p = *gargv ;
  936.       else usage() ;
  937.       switch (c) {
  938.       case 'C':
  939.         codingscheme = p;
  940.         break ;
  941.       case 'F':
  942.         familyname = p;
  943.         break ;
  944.       case 'c':
  945.         car = atoi(p) ;
  946.         break ;
  947.       case 's':
  948.         designsize = fixword(atof(p));
  949.         if (designsize < 1048576) {
  950.           fprintf(stderr, " Design size %f out of range!\n",
  951.                   unfixword(designsize));
  952.           jumpout() ;
  953.         }
  954.       case 'h':
  955.         hesc = atoi(p) ;
  956.         flags |= HORZESC ;
  957.         break ;
  958.       case 'v':
  959.         vesc = atoi(p) ;
  960.         flags |= VERTESC ;
  961.         break ;
  962.       case 'x':
  963.         xoff = atoi(p) ;
  964.         flags |= XOFFSET ;
  965.         break ;
  966.       case 'y':
  967.         yoff = atoi(p) ;
  968.         flags |= YOFFSET ;
  969.         break ;
  970.       case 'W':
  971.         tfwid = fixword(atof(p)) ;
  972.         flags |= TFMWIDTH ;
  973.         break ;
  974.       case 'H':
  975.         tfhgt = fixword(atof(p)) ;
  976.         flags |= TFMHEIGHT ;
  977.         break ;
  978.       case 'D':
  979.         tfdep = fixword(atof(p)) ;
  980.         flags |= TFMDEPTH ;
  981.         break ;
  982.       case 'I':
  983.         tfital = fixword(atof(p)) ;
  984.         flags |= TFMITALIC ;
  985.         break ;
  986.       case 'f':
  987.         optionfile(p) ;
  988.         break ;
  989.       case 'p':
  990.         numparam = atoi(p);
  991.         if (numparam < 1 || numparam > 30) {
  992.           fprintf(stderr, " Parameter count %d out of range!\n", numparam);
  993.           jumpout();
  994.         }
  995.         for (i=0; i<numparam; i++)
  996.           if (++gargv,--gargc) parameters[i] = fixword(atof(*gargv)) ;
  997.           else {
  998.             fprintf(stderr, " Not enough parameters (-p)!\n");
  999.             jumpout() ;
  1000.           }
  1001.         break ;
  1002.       default:
  1003.         usage() ;
  1004.       }
  1005.     } else  {
  1006.       checkchar() ;
  1007.       if (flags & TFMWIDTH)
  1008.         tfmindex[car] = add_tfmwidth(tfwid);
  1009.       if (flags & TFMDEPTH)
  1010.         depindex[car] = add_tfmdepth(tfdep);
  1011.       if (flags & TFMHEIGHT)
  1012.         hgtindex[car] = add_tfmheight(tfhgt);
  1013.       if (flags & TFMITALIC)
  1014.         italindex[car] = add_tfmitalic(tfital);
  1015.       horzesc[car] = hesc ;
  1016.       vertesc[car] = vesc ;
  1017.       xoffset[car] = xoff ;
  1018.       yoffset[car] = yoff ;
  1019.       filename[car] = *gargv ;
  1020.       charflags[car] = flags ;
  1021.       car++ ;
  1022.       flags = 0;
  1023.     }
  1024.   }
  1025. }
  1026.  
  1027. main(argc, argv)
  1028.      int argc ;
  1029.      char *argv[] ;
  1030. {
  1031.   initialize() ;
  1032.   dialog(argc, argv) ;
  1033.   hppp = round((resolution<<16) / 72.27) ;
  1034.   add_suffix(pkname, "pk") ;
  1035.   add_suffix(tfmname, "tfm") ;
  1036.   if (!strcmp(pkname, "-")) pkfile = stdout;
  1037.   else if ((pkfile = fopen(pkname, "w")) == NULL) {
  1038.     fprintf(stderr, " Can't open PK file %s!\n", pkname);
  1039.     jumpout() ;
  1040.   }
  1041.   if (!strcmp(tfmname, "-")) tfmfile = stdout ;
  1042.   else if ((tfmfile = fopen(tfmname, "w")) == NULL) {
  1043.     fprintf(stderr, " Can't open TFM file %s!\n", tfmname);
  1044.     jumpout();
  1045.   }
  1046.   writepreamble() ;
  1047.   for (car = 0 ; car < MAXPKCHAR ; car++)
  1048.     if (filename[car]) {
  1049.       readcharacter() ;
  1050.       shipcharacter() ;
  1051.     }
  1052.   writepostamble() ;
  1053.   writetfmfile() ;
  1054.   if (pkfile != stdout) fclose(pkfile) ;
  1055.   if (tfmfile != stdout) fclose(tfmfile) ;
  1056.   exit(0);
  1057. }
  1058.  
  1059.